package com.csx.micrometer.invoke.core.outbound.resttemplate;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.web.client.RestTemplate;

import java.util.List;

/**
 * 针对 RestTemplate 对象的后置处理器，用于将 记录调用指标的 拦截器加入进去
 * 该后置处理器不仅处理了普通的RestTemplate，还处理了带有 {@link org.springframework.cloud.client.loadbalancer.LoadBalanced}注解的
 *  除了这一种初始化方式外，还有第二种初始化方式，详细参考 {@link org.springframework.beans.factory.SmartInitializingSingleton}
 * @author cuisongxu
 * @date 2022/12/4 14:57
 */
public class MicrometerRestTemplateBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     *
     * @param bean  bean
     * @param beanName beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof RestTemplate) {
            // 获取Bean上面的注解
            LoadBalanced annotation = applicationContext.findAnnotationOnBean(beanName, LoadBalanced.class);
            RestTemplate restTemplate = (RestTemplate) bean;
            List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();
            if(annotation != null) {
                LoadBalancerInterceptor micrometerLoadBalancerOutboundInterceptor = applicationContext.getBean("micrometerLoadBalancerOutboundInterceptor", LoadBalancerInterceptor.class);
                interceptors.add(micrometerLoadBalancerOutboundInterceptor);
            }else {
                ClientHttpRequestInterceptor micrometerRestTemplateOutboundInterceptor = applicationContext.getBean("micrometerRestTemplateOutboundInterceptor", ClientHttpRequestInterceptor.class);
                interceptors.add(micrometerRestTemplateOutboundInterceptor);
            }
        }
        return bean;
    }


}
